package com.cdn.common.core.utils;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

public final class SSHUtils {
    /**
     * 通过 SSH 执行命令
     * @param host SSH 主机地址
     * @param port SSH 端口
     * @param user SSH 用户名
     * @param password SSH 密码
     * @param command 要执行的命令
     * @return 命令执行结果
     * @throws Exception
     */
    public static String executeSSHCommand(String host, int port, String user, String password, String command) throws Exception {
        JSch jsch = new JSch();
        Session session = jsch.getSession(user, host, port);
        session.setPassword(password);

        // 为了避免首次连接时的提示，设置 StrictHostKeyChecking 为 no
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();

        ChannelExec channel = (ChannelExec) session.openChannel("exec");
        channel.setCommand(command);
        channel.setErrStream(System.err);

        // 获取命令执行的输出
        InputStream inputStream = channel.getInputStream();
        channel.connect();

        // 读取命令输出
        StringBuilder output = new StringBuilder();
        int readByte;
        while ((readByte = inputStream.read()) != -1) {
            output.append((char) readByte);
        }

        channel.disconnect();
        session.disconnect();

        return output.toString();
    }

    /**
     * 上传配置文件到目标节点
     * @param host 主机地址
     * @param port SSH 端口
     * @param user SSH 用户名
     * @param password SSH 密码
     * @param fileContent 配置文件内容
     * @param remoteFilePath 远程路径
     * @throws Exception
     */
    public static void uploadFile(String host, int port, String user, String password, String fileContent, String remoteFilePath) throws Exception {
        JSch jsch = new JSch();
        Session session = jsch.getSession(user, host, port);
        session.setPassword(password);

        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();

        // 使用 SFTP 将文件上传到目标主机
        ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
        channelSftp.connect();

        // 上传文件
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileContent.getBytes());
        channelSftp.put(byteArrayInputStream, remoteFilePath);
        channelSftp.disconnect();

        session.disconnect();
    }

    /**
     * 执行命令
     * @param command 要执行的命令
     * @throws IOException
     */
    public static void executeLocalCommand(String command) throws IOException {
        Process process = new ProcessBuilder(command.split(" ")).start();
        try {
            process.waitFor();
        } catch (InterruptedException e) {
            throw new IOException("命令执行失败", e);
        }
    }

    public static void uploadJarFile(String sshHost, String sshUser, String sshKey,Integer port, String jarFilePath, String installDir) {
        try {
            JSch jsch = new JSch();

            // 设置密码
            Session session = jsch.getSession(sshUser, sshHost, port);
            session.setPassword(sshKey);  // 设置密码
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            // 打开SFTP通道
            ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
            sftpChannel.connect();

            // 上传文件
            sftpChannel.put(jarFilePath + "/cdn-modules-nodes-client.jar", installDir);

            sftpChannel.disconnect();
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void executeRemoteJarCommand(String sshHost, String sshUser, String sshKey, Integer port, String startCommand) {
        try {
            JSch jsch = new JSch();

            // 设置密码进行 SSH 认证
            Session session = jsch.getSession(sshUser, sshHost, port);
            session.setPassword(sshKey);  // 设置密码
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            // 执行启动命令
            ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
            channelExec.setCommand(startCommand);

            channelExec.connect();

            // 获取命令输出
            InputStream inputStream = channelExec.getInputStream();
            byte[] tmp = new byte[1024];
            while (true) {
                while (inputStream.available() > 0) {
                    int i = inputStream.read(tmp, 0, 1024);
                    if (i < 0) break;
                    System.out.print(new String(tmp, 0, i));
                }
                if (channelExec.isClosed()) {
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee) {}
            }

            channelExec.disconnect();
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String executeRemoteCheckJavaVersionCommand(String sshHost, String sshUser, String sshKey, Integer port, String checkJavaVersionCommand) {
        try {
            JSch jsch = new JSch();
            Session session = jsch.getSession(sshUser, sshHost, port);
            session.setPassword(sshKey);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            // 执行命令
            ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
            channelExec.setCommand(checkJavaVersionCommand);

            InputStream inputStream = channelExec.getInputStream();
            channelExec.connect();

            // 读取命令输出
            StringBuilder output = new StringBuilder();
            byte[] tmp = new byte[1024];
            while (true) {
                while (inputStream.available() > 0) {
                    int i = inputStream.read(tmp, 0, 1024);
                    if (i < 0) break;
                    output.append(new String(tmp, 0, i));
                }
                if (channelExec.isClosed()) {
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee) {}
            }

            channelExec.disconnect();
            session.disconnect();

            return output.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void executeRemoteInstallJavaCommand(String sshHost, String sshUser, String sshKey, Integer port, String installJavaCommand) {
        try {
            JSch jsch = new JSch();

            // 设置密码进行 SSH 认证
            Session session = jsch.getSession(sshUser, sshHost, port);
            session.setPassword(sshKey);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            // 执行启动命令
            ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
            channelExec.setCommand(installJavaCommand);

            channelExec.connect();

            // 获取命令输出
            InputStream inputStream = channelExec.getInputStream();
            byte[] tmp = new byte[1024];
            while (true) {
                while (inputStream.available() > 0) {
                    int i = inputStream.read(tmp, 0, 1024);
                    if (i < 0) break;
                    System.out.print(new String(tmp, 0, i));
                }
                if (channelExec.isClosed()) {
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee) {}
            }

            channelExec.disconnect();
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void executeRemoteCreateDirCommand(String sshHost, String sshUser, String sshKey, Integer port, String createDirCommand) {
        try {
            JSch jsch = new JSch();

            // 设置密码进行 SSH 认证
            Session session = jsch.getSession(sshUser, sshHost, port);
            session.setPassword(sshKey);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            // 执行启动命令
            ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
            channelExec.setCommand(createDirCommand);

            channelExec.connect();

            // 获取命令输出
            InputStream inputStream = channelExec.getInputStream();
            byte[] tmp = new byte[1024];
            while (true) {
                while (inputStream.available() > 0) {
                    int i = inputStream.read(tmp, 0, 1024);
                    if (i < 0) break;
                    System.out.print(new String(tmp, 0, i));
                }
                if (channelExec.isClosed()) {
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee) {}
            }

            channelExec.disconnect();
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
